home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0992.ARJ / DUNHAM.LS8 < prev    next >
Text File  |  1992-04-20  |  32KB  |  930 lines

  1. /* Listing #8: ibm.c     signal handling & stack traceback */
  2.  
  3. #include <stdio.h>
  4. #include <signal.h>        /* for signal definitions */
  5. #include <string.h>        /* for strtok */
  6. #include <a.out.h>        /* to get COFF file header */
  7. #include <sys/debug.h>        /* to get tbtable */
  8.  
  9. /*----------------- local defines --------------------*/
  10. #undef PROTOTYPES         /* ignore prototype info */
  11. #undef DEBUGPRINT        /* we don't want debug info */
  12. #define STACKDUMP 1        /* set to 1 to get 32bit stack dumps */
  13. #define FRAMEDUMP 1        /* set to 1 to dump each stack frame */
  14. #define PARAMDUMP 0        /* set to 1 to get parameter dumps */
  15. #define LOCALSYMDUMP 0        /* set to 1 to get local symbol dumps */
  16.  
  17. #define JUMPPC 2        /* how to find next program counter */
  18. #define JUMPSP 0        /* how to find next stack pointer */
  19. #define PCADJUST  0x1000020a    /* determined experimentally */
  20. #define MAXLEVEL 40        /* maximum number of nested subroutine calls */
  21. #define MAXPARAM 40        /* maximum number of subroutine parameters */
  22. #define DUMPSIZE 256        /* size of stack dump */
  23. #define NSIGNAL 31              /* #signals to describe in text array */
  24. #define STREQ(a,b)  (strcmp((a),(b))==0)
  25. #define STRNEQ(a,b) (strcmp((a),(b))!=0)
  26. #define CNULL '\0'
  27.  
  28. #ifdef PROTOTYPES
  29. # define P_(s) s
  30. #else
  31. # define P_(s) ()
  32. #endif
  33. #ifdef DEBUGPRINT
  34. # define DBPRINT(s) printf s
  35. #else
  36. # define DBPRINT(s) 
  37. #endif
  38.  
  39. /*----------------- external functions --------------------*/
  40. char *malloc();
  41. char *getenv();
  42.  
  43. /*----------------- internal functions --------------------*/
  44. static void trb_exefind P_((int argc, char *argv));
  45. static void trb_exeinfo();
  46. static void trb_stackdump P_((unsigned long start, int nn, FILE **fp));
  47. static void trb_framedump P_((unsigned long sp, unsigned long pc,
  48.                              unsigned long fremeend, FILE **fp));
  49. static void trb_getline P_((int nlevel));
  50. static void trb_symbols P_((int ilevel, FILE fp, FILE fp2));
  51. static void trb_traceback P_((int nlevel));
  52. void trb_userinfo P_((FILE fp));
  53. void trb_handle P_((int sig,int code,struct sigcontext *scp));
  54. static void trb_sigtextinit();
  55. static char *trb_codetext P_((int sig, int code));
  56. static void trb_signal();
  57. void trb_signalinit P_((int argc, char *argv[]));
  58. static char *strstr();
  59.  
  60. /*----------------- structure definitions -----------------*/
  61. struct levelstr
  62.   {unsigned long stackpointer;
  63.    unsigned long programcounter;
  64.    unsigned long frameend;
  65.    long fileaddr,funcaddr;
  66.    char funcname[256];
  67.    char filename[256];
  68.    int found;
  69.    int line;
  70.    int nparam;
  71.   };
  72. struct exestr
  73.   {int nsym,nline,nstring;
  74.    unsigned long magic;
  75.    long stroffset;
  76.    long symoffset;
  77.    long lineoffset;
  78.    long textoffset;
  79.    char name[256];
  80.   };
  81.  
  82.  
  83. /*----------------- global variables ----------------------*/
  84. char   sigtext[NSIGNAL+1][64];
  85. struct levelstr level[MAXLEVEL];
  86. struct exestr exe;
  87. FILE   *fpcrash,*fpstackdump,*fpframedump; 
  88.               /* pointers to files CRASH, STACKDUMP, FRAMEDUMP */
  89.  
  90. /****************************************************************/
  91. /*    trb_exefind                        */
  92. /*    find the path of the file we are executing        */
  93. /****************************************************************/
  94. void trb_exefind(argc,argv)
  95. int argc;
  96. char *argv[];
  97. {
  98.   FILE *fp;
  99.   int ll;
  100.   char name[256],*path;
  101.   char *ptr,trial[256];
  102. /*---------------------------------*/
  103. /* get name of program */
  104.   strcpy(name,argv[0]);
  105.   
  106. /* 1: if name contains a slash, assume it is the direct path */
  107.   ptr= strchr(name,'/');
  108.   if(ptr!=NULL)
  109.     {strcpy(trial,name);
  110.      fp= fopen(trial,"r");
  111.      if(fp!=NULL)
  112.        {fclose(fp);strcpy(exe.name,trial);return;}
  113.     }
  114.       
  115. /* 2: look in the user's path */
  116.   ptr= getenv("PATH");
  117.   ll= strlen(ptr);
  118.   path= malloc(ll+1);
  119.   strcpy(path,ptr);
  120. /* separate path string into its components */
  121.   ptr= strtok(path,":");
  122.   while(ptr!=NULL)
  123.     {strcpy(trial,ptr);
  124.      strcat(trial,"/");
  125.      strcat(trial,name);
  126.      DBPRINT(("trial exe is %s \n",trial));
  127.      fp= fopen(trial,"r");
  128.      if(fp!=NULL) {fclose(fp);strcpy(exe.name,trial);free(path);return;}
  129.      ptr= strtok(NULL,":");
  130.     }
  131.  
  132. /* 3: try the local directory in case it is not in the path */
  133.   strcpy(trial,"./");
  134.   strcat(trial,name);
  135.   DBPRINT(("trial exe is %s \n",trial));
  136.   fp= fopen(trial,"r");
  137.   if(fp!=NULL){fclose(fp);strcpy(exe.name,trial);return;}
  138.  
  139. } /* end of trb_exefind */
  140.  
  141. /****************************************************************/
  142. /*    trb_exeinfo                        */
  143. /*    get needed info from executable file header        */
  144. /****************************************************************/
  145. void trb_exeinfo()
  146. {
  147.   int i,j,k,ll,status,nline;
  148.   unsigned long magic;
  149.   FILE *fp,*fp2;
  150.   struct filehdr fheader;    /* exe file header (from filehdr.h) */
  151.   struct aouthdr aheader;    /* exe aux  header (from aouthdr.h) */
  152.   struct scnhdr  sheader;    /* exe section header (from scnhdr.h) */
  153.   struct lineno  linesym;    /* line number entry (from linenum.h) */
  154.   struct syment symbol;        /* symbols (from syms.h) */
  155.   AUXENT aux;
  156.   short fakeaux[9];
  157.   struct ldhdr lheader;
  158.   struct ldsym loadsym;
  159.   unsigned long hexdump,nseek,line,address,contents;
  160.   char *ptr,ttext[512],symbolname[80],funcname[80];
  161.   ulong toc;
  162. /*--------------------*/
  163. /* open exe file */
  164.   fp= fopen(exe.name,"r");
  165.   if(fp==NULL)
  166.     {printf("cant open %s\n",exe.name);
  167.      exit(1);}
  168.   fp2= fopen(exe.name,"r");
  169.   
  170. /* --------------------
  171.    read the file header 
  172. ----------------------- */
  173.   status= fread(&fheader,FILHSZ,1,fp);
  174.   if(status==0) {printf("could not read file header\n"); exit(2);}
  175.  
  176. /* get the magic number */
  177.   exe.magic= fheader.f_magic;
  178.  
  179. /* how big is the symboltable header */
  180.   exe.nsym= fheader.f_nsyms;
  181.   DBPRINT(("nsym=%d\n",exe.nsym));
  182.   if(exe.nsym==0) exit(4);
  183.  
  184. /* get file offset for symboltable header */
  185.   exe.symoffset= fheader.f_symptr;
  186.  
  187. /* -------------------------------------------
  188.    read the auxillary header (we don't use it)
  189. ---------------------------------------------- */
  190.   status= fread(&aheader,sizeof(aheader),1,fp);
  191.   if(status==0) {printf("could not read aux header\n"); exit(2);}
  192.   
  193. /* --------------------------------------------------
  194.    read section headers to get offset to line numbers 
  195. ----------------------------------------------------- */
  196.   i= 0;
  197.   strcpy(ttext,"  ");
  198.   while(i<8)
  199.     {status= fread(&sheader,SCNHSZ,1,fp);
  200.      if(status==0) {printf("could not read sec header\n"); exit(2);}
  201.      DBPRINT(("section header = %s size=%x offset=0x%x %d %o\n",
  202.        sheader.s_name, sheader.s_size, sheader.s_scnptr, sheader.s_scnptr, 
  203.        sheader.s_scnptr));
  204.     if(strcmp(sheader.s_name,".text")==0)
  205.       {exe.nline= sheader.s_nlnno;
  206.        exe.textoffset= sheader.s_scnptr; 
  207.        exe.lineoffset= sheader.s_lnnoptr; }
  208.     if(strcmp(sheader.s_name,".debug")==0)
  209.       exe.stroffset= sheader.s_scnptr;
  210.      i++;
  211.     }
  212.  
  213.  
  214.     
  215. #if 0
  216. /* print all line numbers */
  217.   nseek= exe.lineoffset;
  218.   printf("line number nseek =%ld %o %x\n",nseek,nseek,nseek);
  219.   fseek(fp,nseek,0);
  220.   for(i=0;i<exe.nline;i++)
  221.     {status= fread(&linesym,LINESZ,1,fp);
  222.      if(status==0)printf("could not read line symbol %d\n",i);
  223.      line= linesym.l_lnno;
  224.      address= linesym.l_addr.l_paddr;
  225.      if(line!=0)
  226.         printf("linenum i=%d line#=%d addr=%x \n",i,line,address);
  227.      if(line==0)
  228.        {nseek= exe.symoffset+(address+3)*SYMESZ;
  229.         fseek(fp2,nseek,0);
  230.         status= fread(&symbol,SYMESZ,1,fp2);
  231.        if(symbol.n_zeroes==0)
  232.          {nseek= exe.stroffset + symbol.n_offset;
  233.           fseek(fp2,nseek,0);  funcname[0]=CNULL;
  234.           ptr= fgets(funcname,80,fp2);
  235.           printf("%d %s \n",address,funcname);
  236.          }
  237.        else
  238.           printf("%d %s \n",address,symbol.n_name);
  239.        }
  240.     }
  241. #endif
  242.  
  243. #if 0
  244. /* print all symbols */
  245.   nseek= exe.symoffset;
  246.   printf("symbol table nseek =%ld %o %x\n",nseek,nseek,nseek);
  247.   fseek(fp,nseek,0);
  248.   for(i=0;i<exe.nsym;i++)
  249.     {status= fread(&symbol,SYMESZ,1,fp); /* sizeof(sym) wrong due to alignment */
  250.      if(status==0)printf("could not read symbol %d\n",i);
  251.      if(symbol.n_zeroes==0)
  252.        {nseek= exe.stroffset + symbol.n_offset;
  253.         fseek(fp2,nseek,0);  symbolname[0]= CNULL;
  254.         ptr= fgets(symbolname,80,fp2);
  255.         printf("%s ((%d)) ",symbolname,i);
  256.        }
  257.      else
  258.        printf("%s (%d) ",symbol.n_name,i);
  259.      if(symbol.n_sclass==C_FUN)printf(" FUNCTION ");
  260.      else if(symbol.n_sclass==C_LSYM)printf(" local sym ");
  261.      else if(symbol.n_sclass==C_PSYM)printf(" parameter ");
  262.      else if(symbol.n_sclass==C_FCN)printf(" "); /* .bf or .ef */
  263.      else if(symbol.n_sclass==C_DECL)printf(" decl ");
  264.      else if(symbol.n_sclass==C_FILE)printf(" FILENAME ");
  265.      else if(symbol.n_sclass==C_HIDEXT)printf(" hidext ");
  266.      else printf(" sclass=%d ",symbol.n_sclass);
  267.      
  268.      printf(" section=%d value=%d %x type=%x naux=%d\n",
  269.            symbol.n_scnum, symbol.n_value,symbol.n_value, symbol.n_type,
  270.            symbol.n_numaux);
  271.      if(symbol.n_numaux!=0)
  272.        {for(j=0;j<symbol.n_numaux;j++)
  273.           {
  274.            status= fread(fakeaux,AUXESZ,1,fp);
  275.            for(k=0;k<9;k++)printf("%4x",fakeaux[k]);
  276.            printf("\n");
  277.            i++;
  278.           }
  279.        }
  280.     }
  281. #endif    
  282.   fclose(fp);
  283.   fclose(fp2);
  284. } /* end of trb_exeinfo */
  285.   
  286. /****************************************************************/
  287. /*    trb_stackdump                        */
  288. /*    dump the stack                        */
  289. /****************************************************************/
  290. static void trb_stackdump(start,nn,fp0)
  291. unsigned long start;
  292. int nn;
  293. FILE **fp0;
  294. {
  295.   int i,j;
  296.   FILE *fp;
  297. /*------------------------------------------------------*/
  298.   /* start= 0x2003fa00;    uncomment to dump the string area (ibm only) */
  299.   fp= *fp0;
  300.   if(fp==0)
  301.     {fp= fopen("STACKDUMP","a"); /* open for append */
  302.      if(fp==NULL) fp= stdout; /* if failure, use standard out */
  303.      *fp0= fp;                /* save it in case we have two crashes */
  304.     }
  305.   trb_userinfo(fp);
  306.   for (i=0; i<nn;i++)
  307.     {fprintf(fp,"%08x ", (long)start);
  308.      fprintf(fp,"%08x ", *(unsigned long *)(start));
  309.      for(j=0;j<4;j++,start++)
  310.        fprintf(fp,"%c",   isprint(*(unsigned char *)(start))
  311.              ? *(unsigned char *)(start) : ' ');
  312.      fprintf(fp,"\n");
  313.     }
  314.   fclose(fp);
  315. } /* end of trb_stackdump */
  316.  
  317. /****************************************************************/
  318. /*    trb_framedump                        */
  319. /*    dump a stack frame                    */
  320. /****************************************************************/
  321. static void trb_framedump(stackpointer,programcounter,frameend,fp0)
  322. unsigned long stackpointer,programcounter,frameend;
  323. FILE **fp0;
  324. {  
  325.   int j;
  326.   unsigned long stackaddress,stackvalue,pc2;
  327.   FILE *fp;
  328. /*------------------------------------------------------*/
  329.   fp= *fp0;
  330.   if(fp==0)
  331.     {fp= fopen("FRAMEDUMP","a"); 
  332.      if(fp==NULL) fp= stdout;
  333.      trb_userinfo(fp);
  334.      *fp0= fp;
  335.     }
  336.   pc2= ibm_convert(programcounter);
  337.   fprintf(fp,"-----------------------------------\n");
  338.   fprintf(fp,"sp= %08x pc= %08x pc2= %08x\n",stackpointer,programcounter,pc2);
  339.   j= 0;
  340.   stackaddress= stackpointer;
  341.   while(stackaddress<frameend)
  342.     {stackvalue= *( (long *)stackaddress);
  343.      fprintf(fp," %8x",stackvalue);
  344.      j++;
  345.      if(j==8) {fprintf(fp,"\n");j= 0;}
  346.      stackaddress= stackaddress+4;
  347.     }
  348.   if(j!=0)fprintf(fp,"\n");
  349.   fprintf(fp,"-----------------------------------\n");
  350. } /* end of trb_framedump */
  351.  
  352. /****************************************************************/
  353. /*    trb_getline                        */
  354. /*    find file lines matching addresses            */
  355. /****************************************************************/
  356. void trb_getline(nlevel)
  357. int nlevel;
  358. {
  359.   struct lineno  linesym;    /* line number entry (from linenum.h) */
  360.   struct syment symbol;        /* symbols (from syms.h) */
  361.   struct syment symbol2;        /* symbols (from syms.h) */
  362.   AUXENT aux;
  363.   short fakeaux[9];
  364.   FILE *fp,*fp2;
  365.   unsigned long address,match,lastaddress;
  366.   unsigned long contents;
  367.   int type,line,funcsym,naux,lineadd;
  368.   int i,j,k,ll,il,ip,status;
  369.   long fileaddr,funcaddr,magic,nseek;
  370.   int iff,ii;
  371.   char *ptr,ttext[256];
  372.   char funcname[256],filename[256];
  373. /*----------------------*/
  374. /* initialize */
  375.   address= -1; funcsym= 0;
  376.   lastaddress= 0xFFFF;
  377.   for(i=0;i<MAXLEVEL;i++)level[i].found= 0;
  378.   DBPRINT(("in trb_getline: nlevel=%d pc[0]=%x\n",nlevel,level[0].programcounter));
  379.  
  380. /* use first file pointer to read symbol table */
  381.   fp= fopen(exe.name,"r");
  382.   if(fp==NULL){printf("cant open %s\n",exe.name);exit(1);}
  383. /* use second file pointer to read the string table */
  384.   fp2= fopen(exe.name,"r");
  385.  
  386. /* search thru line numbers (in their own section) */
  387.   nseek= exe.lineoffset;
  388.   fseek(fp,nseek,0);
  389.   lineadd= 0;
  390.   for(i=0;i<exe.nline;i++)
  391.     {status= fread(&linesym,LINESZ,1,fp);
  392.      if(status==0)printf("could not read line symbol %d\n",i);
  393.      if(linesym.l_lnno!=0) 
  394.        {line= linesym.l_lnno; address= linesym.l_addr.l_paddr;}
  395.      if(linesym.l_lnno==0)    /* we are at the start of a function */
  396.        {funcsym= linesym.l_addr.l_paddr;
  397.         funcsym= funcsym+3;
  398.         nseek= exe.symoffset+ funcsym*SYMESZ;    /* get the function's name */
  399.         fseek(fp2,nseek,0);
  400.         status= fread(&symbol,SYMESZ,1,fp2);
  401.         status= fread(&symbol2,SYMESZ,1,fp2);    /* read .bf to get lineadd */
  402.         naux= symbol2.n_numaux;
  403.         if(naux>0)
  404.           {status= fread(fakeaux,AUXESZ,1,fp2);
  405.            lineadd= fakeaux[2];    /* x_sym.x_misc.x_lnsz.x_lnno */
  406.           }
  407.     /* get the name of the function */
  408.         if(symbol.n_zeroes==0)
  409.           {nseek= exe.stroffset + symbol.n_offset;
  410.            fseek(fp2,nseek,0);  funcname[0]= CNULL;
  411.            ptr= fgets(funcname,80,fp2);
  412.           }
  413.         else
  414.           strcpy(funcname,symbol.n_name);
  415.         ptr= strchr(funcname,':');
  416.         if(ptr!=NULL) *ptr= CNULL;
  417.        }
  418. /* does this address match one of ours? */
  419.      for(iff=0;iff<nlevel;iff++)
  420.        {if(level[iff].found==0)
  421.          {match= level[iff].programcounter;
  422.           if(address==match)
  423.             {DBPRINT(("exact match of %x found at line %d\n",match,line));
  424.              level[iff].found= funcsym;
  425.              strcpy(level[iff].funcname,funcname);
  426.              strcpy(level[iff].filename," ");
  427.              level[iff].line= line+lineadd;
  428.             }
  429.           else if(address>match && lastaddress<match && lastaddress>(match-64))
  430.             {
  431.              DBPRINT(("match of %x before line %d, lastaddress=%x address=%x\n",
  432.              match,line,lastaddress,address));
  433.              level[iff].found= funcsym;
  434.              strcpy(level[iff].funcname,funcname);
  435.              strcpy(level[iff].filename," ");
  436.              level[iff].line= line-1+lineadd;
  437.             }
  438.          }
  439.        }
  440.      lastaddress= address;
  441.     } /* end of loop over nline */
  442.  
  443. /* now find the file names */
  444.   nseek= exe.symoffset;
  445.   fseek(fp,nseek,0);
  446.   strcpy(filename,"");
  447.   for(i=0;i<exe.nsym;i++)
  448.     {status= fread(&symbol,SYMESZ,1,fp);
  449.      if(status==0)printf("could not read symbol %d\n",i);
  450.      if(symbol.n_sclass==C_FILE)
  451.        {if(symbol.n_zeroes==0)
  452.           {nseek= exe.stroffset + symbol.n_offset;
  453.            fseek(fp2,nseek,0);  filename[0]= CNULL;
  454.            ptr= fgets(filename,80,fp2);
  455.           }
  456.         else
  457.           strcpy(filename,symbol.n_name);
  458.        }
  459.      for(iff=0;iff<nlevel;iff++)
  460.        {if(level[iff].found==i)
  461.           strcpy(level[iff].filename,filename);
  462.        }
  463.     }
  464.  
  465.   fclose(fp);
  466.   fclose(fp2);
  467. } /* end of trb_getline */
  468.  
  469. /****************************************************************/
  470. /*    trb_params                        */
  471. /*    print one level of parameters                */
  472. /****************************************************************/
  473. void trb_params(ilevel,fp,fp2)
  474. int ilevel;
  475. FILE *fp, *fp2;
  476. {
  477.   struct syment symbol;        /* symbols (from syms.h) */
  478.   AUXENT aux;
  479.   int i,j,ll,status,isym,naux,nparam;
  480.   long nseek,address,stackbase,off,contents;
  481.   char *ptr,symbolname[80],symboltype[80];
  482.   char params[1024];
  483.   char values[MAXPARAM][80];
  484. /*------------------------------------*/
  485.   strcpy(params,level[ilevel].funcname);
  486.   strcat(params,"(");
  487.   nparam= 0;
  488.   isym= level[ilevel].found;
  489.   nseek= exe.symoffset + isym*SYMESZ;
  490.   fseek(fp,nseek,0);
  491.   for(i=isym;i<exe.nsym;i++)
  492.     {status=fread(&symbol,SYMESZ,1,fp);    /* sizeof(sym) wrong due to alignment */
  493.      if(status==0)printf("could not read symbol %d\n",i);
  494.      naux= symbol.n_numaux;
  495.      if(symbol.n_sclass==C_FCN) /* .bf or .ef */
  496.        if(STREQ(symbol.n_name,".ef"))goto print;    
  497.      if(symbol.n_sclass==C_PSYM) /* a parameter */
  498.        {if(symbol.n_zeroes==0)
  499.           {nseek= exe.stroffset + symbol.n_offset;
  500.            fseek(fp2,nseek,0);  symbolname[0]= CNULL;
  501.            ptr= fgets(symbolname,80,fp2);
  502.           }
  503.         else
  504.           strcpy(symbolname,symbol.n_name);   
  505.         ptr= strchr(symbolname,':');
  506.         if(ptr!=NULL)
  507.           {strcpy(symboltype,ptr); *ptr= CNULL;}
  508.         else symboltype[0]= CNULL;
  509.         strcat(params,symbolname); strcat(params,",");
  510.  
  511.         off= symbol.n_value;
  512.         stackbase= level[ilevel].stackpointer;
  513.         address= stackbase + off;
  514.         ptr= *(long *)address;
  515.  
  516.         if(STREQ(symboltype,":p2"))
  517.           sprintf(values[nparam],"  %s = \"%s\" ",symbolname,ptr);
  518.         else if(STREQ(symboltype,":p-1"))
  519.           sprintf(values[nparam],"  %s = %d 0x%x (long)",
  520.               symbolname,*(long *)address,*(long *)address);
  521.         else if(STREQ(symboltype,":p-3"))
  522.           sprintf(values[nparam],"  %s = %d 0x%x (short)",
  523.         symbolname,*(short *)address,*(short *)address);
  524.         else if(STREQ(symboltype,":p-12"))
  525.           sprintf(values[nparam],"  %s = %f (float)",symbolname,
  526.                 *(float *)address);
  527.         else if(STREQ(symboltype,":p-13"))
  528.           sprintf(values[nparam],"  %s = %f (double)",symbolname,
  529.                 *(double *)address);
  530.         else 
  531.           sprintf(values[nparam],"  %s unknown type    [%s]",
  532.                   symbolname, symboltype);
  533.         nparam++;
  534.        }
  535.      if(naux>0)
  536.        for(j=0;j<naux;j++) status= fread(&aux,AUXESZ,1,fp);
  537.     } /* end of loop over isym */
  538.  
  539. print:
  540. /* change the last comma to an ) */
  541.   ll= strlen(params);
  542.   if(params[ll-1]==',') params[ll-1]= ')'; else strcat(params,")");
  543.   fprintf(fpcrash,"%s\n",params);
  544.   for(i=0;i<nparam;i++)fprintf(fpcrash,"%s\n",values[i]);
  545. } /* end of trb_params */
  546.  
  547. /****************************************************************/
  548. /*    trb_symbols                        */
  549. /*    print local symbols in procedure of interest        */
  550. /****************************************************************/
  551. void trb_symbols(ilevel,fp,fp2)
  552. int ilevel;
  553. FILE *fp, *fp2;
  554. {
  555.   struct syment symbol;        /* symbols (from syms.h) */
  556.   AUXENT aux;
  557.   int i,j,ll,status,isym,naux,nparam;
  558.   long nseek,address,stackbase,off;
  559.   unsigned long dead,live;
  560.   char *ptr,symbolname[80],symboltype[16];
  561.   char ttext[512];
  562.   short int jtemp;  unsigned short jtemp2;
  563.   int itemp;
  564.   float ftemp;
  565.   double dtemp;
  566. /*-----------------------------------*/
  567.   dead= 0xdeadbeef;
  568.   fprintf(fpcrash,"%s \n",level[ilevel].funcname);
  569.   isym= level[ilevel].found;
  570.   nseek= exe.symoffset + isym*SYMESZ;
  571.   fseek(fp,nseek,0);
  572.   for(i=isym;i<exe.nsym;i++)
  573.     {status= fread(&symbol,SYMESZ,1,fp); /* sizeof(sym) wrong due to alignment */
  574.      if(status==0)printf("could not read symbol %d\n",i);
  575.      naux= symbol.n_numaux;
  576.      if(symbol.n_sclass==C_FCN) /* .bf or .ef */
  577.        if(STREQ(symbol.n_name,".ef"))return;
  578.      if(symbol.n_sclass==C_LSYM)
  579.        {if(symbol.n_zeroes==0)
  580.           {nseek= exe.stroffset + symbol.n_offset;
  581.            fseek(fp2,nseek,0);  symbolname[0]= CNULL;
  582.            ptr= fgets(symbolname,80,fp2);
  583.           }
  584.         else
  585.           strcpy(symbolname,symbol.n_name);   
  586.         ptr= strchr(symbolname,':');
  587.         if(ptr!=NULL)
  588.           {strcpy(symboltype,ptr); *ptr= CNULL;}
  589.         else symboltype[0]= CNULL;
  590.         off= symbol.n_value;
  591.         stackbase= level[ilevel].stackpointer;
  592.         address= stackbase + off;
  593.         live= *(long *)address;
  594.         if(live == dead)
  595.           fprintf(fpcrash,"  %s is unassigned \n",symbolname);
  596.         else if(STREQ(symboltype,":2"))
  597.           fprintf(fpcrash,"  %s = \"%s\" (ptr) \n",symbolname,(char *)address);
  598.         else if(STREQ(symboltype,":3"))
  599.            fprintf(fpcrash,"  %s = \"%s\"  \n",symbolname,(char *)address);
  600.         else if(STREQ(symboltype,":4"))
  601.            fprintf(fpcrash,"  %s = \"%s\" \n",symbolname,(char *)address);
  602.         else if(STREQ(symboltype,":-1"))
  603.           fprintf(fpcrash,"  %s = %d 0x%x (long) \n",
  604.         symbolname,*(long *)address,*(long *)address);
  605.         else if(STREQ(symboltype,":-3"))
  606.           fprintf(fpcrash,"  %s = %d 0x%x (short) \n",
  607.         symbolname,*(short *)address,*(short *)address);
  608.         else if(STREQ(symboltype,":-12"))
  609.           fprintf(fpcrash,"  %s = %f 0x%x (float) \n",
  610.         symbolname,*(float *)address,*(float *)address);
  611.         else if(STREQ(symboltype,":-13"))
  612.           fprintf(fpcrash,"  %s = %f 0x%x (double) \n",
  613.         symbolname,*(double *)address,*(double *)address);
  614.         else
  615.           fprintf(fpcrash,"  %s  unknown type     [%s] \n",
  616.            symbolname, symbol.n_value,symbol.n_value, symboltype);
  617.        }
  618.      if(naux>0)
  619.        for(j=0;j<naux;j++) status= fread(&aux,AUXESZ,1,fp);
  620.     } /* end of loop over isym */
  621.  
  622. } /* end of trb_symbols */
  623.  
  624. /****************************************************************/
  625. /*    trb_traceback                        */
  626. /*    print a traceback                     */
  627. /****************************************************************/
  628. void trb_traceback(nlevel)
  629. int nlevel;
  630. {
  631.   int i;
  632.   FILE *fp,*fp2;
  633. /*---------------------------*/
  634.   if(nlevel<1)return;
  635. /* use first file pointer to read the symbol table */
  636.   fp= fopen(exe.name,"r");
  637.   if(fp==NULL){printf("cant open %s\n",exe.name);exit(1);}
  638. /* use second file pointer to read the string table */
  639.   fp2= fopen(exe.name,"r");
  640.  
  641. /* print a traceback to the screen */
  642.   fprintf(fpcrash,"---------- traceback ----------\n");
  643.   for(i=0;i<nlevel;i++)
  644.     {if(level[i].found!=0)
  645.        fprintf(fpcrash,"file %s\t line %d\t function %s() \n",
  646.            level[i].filename, level[i].line, level[i].funcname);
  647.      else
  648.        fprintf(fpcrash,"address %x \n", level[i].programcounter);
  649.     }
  650.  
  651.   fprintf(fpcrash,"---------- parameters ----------\n");
  652.   for(i=0;i<nlevel;i++)
  653.      if(level[i].found!=0) trb_params(i,fp,fp2);
  654.  
  655.   fprintf(fpcrash,"---------- local symbols ----------\n");
  656.   for(i=0;i<nlevel;i++)
  657.      if(level[i].found!=0) trb_symbols(i,fp,fp2);
  658.  
  659.   fclose(fp2);
  660.   fclose(fp);
  661.        
  662. } /* end of trb_traceback */
  663.  
  664.  
  665. /****************************************************************/
  666. /*    ibm_convert                        */
  667. /*    convert stack addresses to coff addresses        */
  668. /****************************************************************/
  669. long ibm_convert(stack)
  670. long stack;
  671. {
  672.   long coff;
  673.   static int first=1;
  674.   if(first==1)
  675.     {coff= PCADJUST;
  676.      DBPRINT(("pcadjust= %d 0x%x \n",coff,coff));
  677.      first=0;
  678.     }
  679.   if(stack>PCADJUST) coff= stack-PCADJUST;
  680.   else coff= stack;
  681.   return(coff);
  682. } /* end of ibm_convert */
  683.  
  684. /****************************************************************/
  685. /*    trb_userinfo                        */
  686. /*    put program name, user, etc into CRASH            */
  687. /****************************************************************/
  688. void trb_userinfo(fp)
  689. FILE *fp;
  690. {
  691.   int ll;
  692.   char *user,host[64],nouser[8];
  693.   time_t timeofday;
  694.   char fulltime[26];
  695. /* get the user's name */
  696.   user= (char *) getlogin();
  697.   if(user==NULL)user= (char *)getpwuid(getuid());
  698.   if(user==NULL){strcpy(nouser,"????"); user=nouser; }
  699.   
  700. /* get the time */
  701.   timeofday=time((time_t *)0);
  702.   strcpy(fulltime,ctime(&timeofday));
  703.   fulltime[24]=CNULL;
  704. /* get the host */
  705.   gethostname(host,64);
  706. /* write to CRASH */
  707.   fprintf(fp,"user=%s host=%s date=%s \n", user,host,fulltime);
  708.   fprintf(fp,"program=%s \n", exe.name);
  709. } /* end of trb_userinfo */
  710.  
  711. /****************************************************************/
  712. /*    trb_handle                        */
  713. /*    handle all signals                    */
  714. /****************************************************************/
  715. void trb_handle(sig,code,scp)
  716. int sig, code;
  717. struct sigcontext *scp;
  718. {
  719.   int i,j,exitflag;
  720.   int nlevel;
  721.   int freg,pcreg;
  722.   unsigned long programcounter,stackpointer,frameend,pc2;
  723.   unsigned long inst;
  724.   unsigned long toc,toc2,link;
  725.   unsigned long as[16],asa;
  726.   char *ptr;
  727.   char *startdump;
  728. /*--------------------*/
  729.   
  730. #if 0   /* set to 1 to dump all general registers */
  731.   for(i=0;i<NGPRS;i++)
  732.     printf(" gpr[%d]    0x%08x \n",i,(*scp).sc_jmpbuf.jmp_context.gpr[i]);
  733. #endif    
  734. /* write to a file called CRASH */
  735.   if(fpcrash==0)fpcrash= fopen("CRASH","a");    /* open for append */
  736.   if(fpcrash==NULL) fpcrash= stdout;        /* write to standard output */
  737.   fprintf(fpcrash,"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n");
  738.   trb_userinfo(fpcrash);
  739. /* print meaningful message for signal */
  740.   fprintf(fpcrash,"%s signal=%d(%d) \n",sigtext[sig],sig,code);
  741.   ptr= trb_codetext(sig,code);
  742.   if(ptr!=NULL) fprintf(fpcrash,"%s\n",ptr);
  743. /* get stack pointer & program counter */
  744.   programcounter= (*scp).sc_jmpbuf.jmp_context.iar; /* from dbx registers */
  745.   stackpointer= (*scp).sc_jmpbuf.jmp_context.gpr[1];
  746.   frameend= *( (long *)stackpointer +JUMPSP);
  747.   pc2= ibm_convert(programcounter);
  748.   DBPRINT((" pc=0x%x sp=0x%x pc2=0x%x\n", programcounter,stackpointer,pc2));
  749.  
  750. #if 0     /* set to 1 to look at other values regards PCADJUST */
  751.   toc= (*scp).sc_jmpbuf.jmp_context.gpr[2];
  752.   toc2= *(long *)toc;
  753.   link= (*scp).sc_jmpbuf.jmp_context.lr;
  754.   printf("toc=%x toc2=%x link=%x \n",toc,toc2,link);
  755.   asa= (*scp).sc_jmpbuf.jmp_context.as.alloc;
  756.   printf("as.alloc=%d %x \n",asa,asa);
  757.   for(i=0;i<16;i++)
  758.     {as[i]= (*scp).sc_jmpbuf.jmp_context.as.srval[i];
  759.      printf("as.srval[%d]= %d %x\n",i,as[i],as[i]);
  760.     }
  761. #endif  
  762.  
  763. #if STACKDUMP
  764.   startdump= (char *) stackpointer;
  765.   startdump= startdump-16;
  766.   trb_stackdump(startdump,DUMPSIZE,&fpstackdump);
  767. #endif
  768.   
  769.  
  770. /* trace the stack & store stack pointers & program counters */  
  771.   nlevel= 0;
  772.   while(stackpointer!= 0)
  773.     {level[nlevel].programcounter= pc2;
  774.      level[nlevel].frameend= 0;
  775.      level[nlevel].stackpointer= stackpointer;
  776.      if(nlevel<MAXLEVEL)nlevel++;
  777. #if FRAMEDUMP
  778.      trb_framedump(stackpointer,programcounter,frameend,&fpframedump);
  779. #endif
  780.      stackpointer= *( (long *)stackpointer +JUMPSP);
  781.      if(stackpointer!=0) frameend= *( (long *)stackpointer +JUMPSP);
  782.      programcounter= *( (long *)stackpointer +JUMPPC);
  783.      pc2= ibm_convert(programcounter);
  784.      if(frameend==0) stackpointer= 0;
  785.     }
  786.  
  787.   trb_exeinfo();        /* get info from file header */
  788.   trb_getline(nlevel);        /* convert addresses to line numbers */
  789.   trb_traceback(nlevel);    /* print a full traceback */
  790.  
  791.   exitflag= 0;
  792.   switch(sig)
  793.     {case SIGTRAP:        exitflag= 1;    break;
  794.      case SIGSEGV:        exitflag= 1;    break;
  795.      case SIGBUS:        exitflag= 1;    break;
  796.      case SIGILL:        exitflag= 1;    break;
  797.      case SIGFPE:        exitflag= 1;    break;
  798.      default:            break;
  799.     } /* end of switch on sig */
  800.   fprintf(fpcrash,"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
  801. #if FRAMEDUMP
  802.   fclose(fpframedump);
  803. #endif
  804.   if(exitflag) 
  805.     {if(fpcrash!=stdout)
  806.        {fclose(fpcrash); 
  807.       /*  system("ls -l CRASH"); */
  808.         }
  809.      exit(sig);
  810.     }
  811.   return;
  812. } /* end of trb_handle */
  813.  
  814. /****************************************************************/
  815. /*    trb_sigtextinit                        */
  816. /*    initialize signal text messages                */
  817. /****************************************************************/
  818. void trb_sigtextinit()
  819. {
  820.   strcpy(sigtext[1],  "SIGHUP:  hangup signal received");
  821.   strcpy(sigtext[2],  "SIGINT:  interrupt signal received");
  822.   strcpy(sigtext[3],  "SIGQUIT: quit signal received");
  823.   strcpy(sigtext[4],  "SIGILL:  illegal instruction (not reset when caught)");
  824.   strcpy(sigtext[5],  "SIGTRAP: trace trap (not reset when caught)");
  825.   strcpy(sigtext[6],  "SIGIOT:  IOT instruction");
  826.   strcpy(sigtext[7],  "SIGEMT:  EMT instruction");
  827.   strcpy(sigtext[8],  "SIGFPE:  floating point exception");
  828.   strcpy(sigtext[9],  "SIGKILL: kill signal received");
  829.   strcpy(sigtext[10],  "SIGBUS:  bus error");
  830.   strcpy(sigtext[11], "SIGSEGV: segmentation violation");
  831.   strcpy(sigtext[12], "SIGSYS:  bad argument to system call");
  832.   strcpy(sigtext[13], "SIGPIPE: write on a pipe with no one to read it");
  833.   strcpy(sigtext[14], "SIGALRM: alarm clock signal received");
  834.   strcpy(sigtext[15], "SIGTERM: received software termination signal");
  835.   strcpy(sigtext[16], "SIGURG:  urgent condition on IO channel");
  836.   strcpy(sigtext[17], "SIGSTOP: sendable stop signal not from tty");
  837.   strcpy(sigtext[18], "SIGTSTP: received stop signal from tty");
  838.   strcpy(sigtext[19], "SIGCONT: continue a stopped process");
  839.   strcpy(sigtext[20], "SIGCHLD: child process has stopped or exited");
  840.   strcpy(sigtext[21], "SIGTTIN: to readers pgrp upon background tty read");
  841.   strcpy(sigtext[22], "SIGTTOU: like TTIN for output if (tp->t_local<OSTOP)");
  842.   strcpy(sigtext[23], "SIGIO:   input/output possible signal");
  843.   strcpy(sigtext[24], "SIGXCPU: exceeded CPU time limit");
  844.   strcpy(sigtext[25], "SIGXFSZ: exceeded file size limit");
  845.   strcpy(sigtext[26], "SIGVTALRM: received virtual time alarm");
  846.   strcpy(sigtext[27], "SIGPROF: received profiling time alarm");
  847.   strcpy(sigtext[28], "SIGWINCH: window changed");
  848.   strcpy(sigtext[30], "SIGUSR1: received user defined signal 1");
  849.   strcpy(sigtext[31], "SIGUSR2: received user defined signal 2");
  850. } /* end if trb_sigtextinit */
  851.  
  852. /****************************************************************/
  853. /*    trb_codetext                        */
  854. /*    initialize code text messages                */
  855. /****************************************************************/
  856. char *trb_codetext(sig,code)
  857. int sig,code;
  858. {
  859.     return(NULL);
  860. } /* end of trb_codetext */
  861.  
  862. /****************************************************************/
  863. /*    trb_signal                        */
  864. /*    initiate trapping of all signals            */
  865. /****************************************************************/
  866. void trb_signal()
  867. {
  868.   int status;
  869. /*---------------------------------------*/
  870.   trb_sigtextinit();
  871. /* trap important signals */
  872.   signal(SIGFPE,trb_handle);  
  873.   signal(SIGBUS,trb_handle);  
  874.   signal(SIGSEGV,trb_handle); 
  875.   signal(SIGILL,trb_handle);  
  876.   signal(SIGTRAP,trb_handle); 
  877.   signal(SIGIOT,trb_handle);  
  878. #if 0
  879.   signal(SIGHUP,trb_handle);  
  880.   signal(SIGINT,trb_handle);  
  881.   signal(SIGQUIT,trb_handle); 
  882.   signal(SIGEMT,trb_handle);  
  883.   signal(SIGSYS,trb_handle);  
  884.   signal(SIGPIPE,trb_handle); 
  885.   signal(SIGALRM,trb_handle); 
  886.   signal(SIGTERM,trb_handle); 
  887.   signal(SIGURG,trb_handle);  
  888.   signal(SIGSTOP,trb_handle); 
  889.   signal(SIGTSTP,trb_handle); 
  890.   signal(SIGCONT,trb_handle); 
  891.   signal(SIGCHLD,trb_handle); 
  892.   signal(SIGTTIN,trb_handle); 
  893.   signal(SIGTTOU,trb_handle); 
  894.   signal(SIGIO,trb_handle);   
  895.   signal(SIGXCPU,trb_handle); 
  896.   signal(SIGXFSZ,trb_handle); 
  897.   signal(SIGVTALRM,trb_handle); 
  898.   signal(SIGPROF,trb_handle); 
  899. #endif
  900. } /* end of trb_signal */
  901.  
  902. /****************************************************************/
  903. /*    ita_signalinit                        */
  904. /*    initiate trapping of all signals            */
  905. /****************************************************************/
  906. void ita_signalinit(argc,argv)
  907. int argc;
  908. char *argv[];
  909. {
  910.   FILE *fp;
  911. /*---------------------------------------*/
  912.   trb_exefind(argc,argv);
  913.  
  914.   fp= fopen("CRASH","w");
  915.   if(fp!=NULL) fclose(fp);    /* remove file called CRASH */
  916.   fpcrash= 0;
  917.   fp= fopen("STACKDUMP","w");
  918.   if(fp!=NULL) fclose(fp);    /* remove file called STACKDUMP */
  919.   fpstackdump= 0;  
  920.   fpstackdump= 0;  
  921.   fp= fopen("FRAMEDUMP","w");
  922.   if(fp!=NULL) fclose(fp);    /* remove file called FRAMEDUMP */
  923.   fpframedump= 0;  
  924.   
  925.   trb_signal();
  926. } /* end of ita_signalinit */
  927.  
  928.  
  929.  
  930.